package dnl.dev.memlog.parser;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.io.FileUtils;

import dnl.dev.memlog.MemlogProject;
import dnl.dev.memlog.sampler.MemSampler;
import dnl.util.ui.ProgressListener;

public class HistogramParser {

	private Map<String, List<ClassInstanceCount>> statisticsMap = new HashMap<String, List<ClassInstanceCount>>();

	private HistogramTokenizingStrategy tokenizingStrategy = new TypeAHistogramTokenizing();

	private MemlogProject memlogProject;

	public HistogramParser(MemlogProject memlogProject) {
		this.memlogProject = memlogProject;
	}

	public List<ClassInstanceCount> getStats(String className) {
		return statisticsMap.get(className);
	}

	public Set<String> getClassNames() {
		return statisticsMap.keySet();
	}

	public int size() {
		return statisticsMap.size();
	}

	public void parse(HistogramsDir histogramsDir, ProgressListener progressListener) {
		File[] histoFiles = histogramsDir.listHistogramFiles();
		int total = histoFiles.length;

		for (int i = 0; i < histoFiles.length; i++) {
			try {
				parseHistogramFile(histoFiles[i]);
				double ratio = (((double) i) / total);
				progressListener.progressed((int) (ratio * 100));
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		progressListener.finished();
	}

	public void addHistogramFile(File f) {
		try {
			parseHistogramFile(f);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public void deleteHistogramFile(File f) {
		String label = f.getName();
		if (label.endsWith(MemSampler.HISTO_FILE_EXT)) {
			label.substring(MemSampler.HISTO_FILE_EXT.length());
		}
		Set<String> keySet = statisticsMap.keySet();
		for (String key : keySet) {
			List<ClassInstanceCount> list = statisticsMap.get(key);
			for (Iterator<ClassInstanceCount> iterator = list.iterator(); iterator.hasNext();) {
				ClassInstanceCount cic = iterator.next();
				if (cic.getSampleLabel().equals(label)) {
					iterator.remove();
				}
			}
		}
	}

	@SuppressWarnings("unchecked")
	private void parseHistogramFile(File f) throws IOException {
		Date date = memlogProject.getFileCreationDate(f.getName());
		String label = memlogProject.getFileCreationLabel(f.getName());
		List<String> readLines = FileUtils.readLines(f);
		for (String string : readLines) {
			try {
				HistogramLineInfo lineInfo = tokenizingStrategy.parse(string);
				if (lineInfo == null) {
					continue;
				}
				List<ClassInstanceCount> stats = ensureList(lineInfo.getClassName());
				stats.add(new ClassInstanceCount(label, date, lineInfo.getNumOfInstances()));
			} catch (Exception e) {
				System.err.println("Skipping an unexpected text in file " + f + ", text='" + string
						+ "'");
			}
		}
	}

	private List<ClassInstanceCount> ensureList(String className) {
		List<ClassInstanceCount> stats = statisticsMap.get(className);
		if (stats == null) {
			stats = new ArrayList<ClassInstanceCount>();
			statisticsMap.put(className, stats);
		}
		return stats;
	}

}
